package winOrDie.GameEngine.P2P;

import java.net.DatagramPacket;
import java.util.ArrayList;
import java.util.Vector;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;

import rice.p2p.commonapi.Node;
import winOrDie.Application.WoD_Application_Data;
import winOrDie.Game.WoD_Game;
import winOrDie.GameEngine.RT.Server_Engine.WoD_RT_Server_Engine;
import winOrDie.GameEngine.RT.mp.MapBoard;
import winOrDie.GameEngine.RT.mp.MapGenerator;
import winOrDie.GameEngine.RT.mp.WoD_MapBoard_Event;
import winOrDie.GameEngine.RT.mp.WoD_MapBoard_Listener;
import winOrDie.Net.WoD_Net_Protocol_ASCII;
import winOrDie.Net.WoD_Net_Protocol_Manager;
import winOrDie.Net.Client.WoD_Client_RT;
import winOrDie.Net.Client.WoD_Client_RT_Event;
import winOrDie.Net.Client.WoD_Client_RT_Listener;
import winOrDie.Net.Client.WoD_Peer;
import winOrDie.Net.Client.WoD_Peers_List;
import winOrDie.Net.Http.httpmsg.WoD_HttpMessage;
import winOrDie.Net.Http.httpmsg.WoD_InfoPartidasActuales;
import winOrDie.Net.P2P.WoD_P2P_Control_Channel;
import winOrDie.Net.P2P.WoD_P2P_Control_Channel_Event;
import winOrDie.Net.P2P.WoD_P2P_Control_Channel_Listener;
import winOrDie.Net.P2P.WoD_ScribeContent;
import winOrDie.Net.RT.WoD_RT_Client_Movement;
import winOrDie.Net.RT.WoD_RT_NTP_Message;
import winOrDie.Net.Server.WoD_Server_Client;
import winOrDie.Net.Server.WoD_Server_Client_List;
import winOrDie.Net.Server.WoD_Server_RT;
import winOrDie.Net.Server.WoD_Server_RT_Event;
import winOrDie.Net.Server.WoD_Server_RT_Listener;
import winOrDie.graphicsInterface.GameRoom.Composite_Options_Event;
import winOrDie.graphicsInterface.RT.Shell_RT_Game;

public class WoD_P2P_Peer
implements WoD_P2P_Control_Channel_Listener,
WoD_Client_RT_Listener,
WoD_Server_RT_Listener, 
WoD_MapBoard_Listener
{
	/**
	 *************************************************************************************** 
	 * Peers and client lists
	 ***************************************************************************************
	 */
	private WoD_Peers_List woDClientPeersList = null;
	private WoD_Server_Client_List woDServerClientList = null;
	
	/**
	 *************************************************************************************** 
	 * Communication channels
	 ***************************************************************************************
	 */
	private WoD_P2P_Control_Channel woDP2PControlChannel = null;
	private WoD_Client_RT woDClientRT = null;
	private WoD_Server_RT woDServerRT = null;
	private WoD_RT_Server_Engine woDRTServerEngine = null;
	

	private int current_Client_ID = 0;
	private boolean Iam_Root = false;
	private String P2P_ROOT = null;
	private long offset = 0L;
	private String MyScribeID = null;
	
	/**
	 *************************************************************************************** 
	 * Threads control
	 ***************************************************************************************
	 */
	private boolean NTP_Loop = false;
	private Thread thread_NTP_CLIENT = null;
	private boolean RT_Messages_Loop = false;
	private Thread thread_RT_Messages = null;
	
	
	public String getMyScribeID() {
		return MyScribeID;
	}

	public void setMyScribeID(String myScribeID) {
		MyScribeID = myScribeID;
	}

	public boolean isIam_Root() {
		return Iam_Root;
	}

	public long getOffset() {
		return offset;
	}



	WoD_Application_Data woDApplicationData = null;
	
	private WoD_Net_Protocol_Manager woDNetProtocolManager = new WoD_Net_Protocol_Manager();
	
	public WoD_P2P_Control_Channel getWoDP2PControlChannel() {
		return woDP2PControlChannel;
	}

	public WoD_Client_RT getWoDClientRT() {
		return woDClientRT;
	}

	public WoD_Peers_List getWoDClientPeersList() {
		return woDClientPeersList;
	}
	
	
	public String getP2P_ROOT() {
		return P2P_ROOT;
	}
	
	public WoD_Peer get_My_WoD_Peer()
	{
		int position = woDClientPeersList.get_positionOfPeer_By_ScribeNode_ID(MyScribeID);
		System.out.println("My position " + position);
		if (position != -1)
		{
			return woDClientPeersList.getWoD_Peers().get(position);
		}
		return null;
	}

	/**
	 *************************************************************************************** 
	 * Listeners
	 ***************************************************************************************
	 */
	private Vector<WoD_P2P_Peer_Listener> listeners = null;
	private Shell_RT_Game shellRTGame = null;
	
	public synchronized void add_WoD_P2P_Peer_Listener(WoD_P2P_Peer_Listener listener)
	{
		listeners.add(listener);
	}
	public synchronized void remove_WoD_P2P_Peer_Listener(WoD_P2P_Peer_Listener listener)
	{
		listeners.remove(listener);
	}
	
	protected void notify_WoD_P2P_Peer_Change(WoD_P2P_Peer_Event event)
	{
		for (WoD_P2P_Peer_Listener listerner : listeners) {
			listerner.on_WoD_P2P_Peer_Change(event);
		}
	}
	
	public WoD_P2P_Peer(Node node, WoD_Application_Data woDApplicationData) {
		woDClientPeersList = new WoD_Peers_List();
		listeners = new Vector<WoD_P2P_Peer_Listener>();
		
		this.woDApplicationData = woDApplicationData;
		woDP2PControlChannel = new WoD_P2P_Control_Channel(node);
		
		woDP2PControlChannel.add_WoD_P2P_Control_Channel_Listener(this);
	}
	
	
	public void send_Join_Game() throws Exception
	{
		byte[] message_To_Send = woDNetProtocolManager.get_Join_Game(woDApplicationData);
		woDP2PControlChannel.getWoDScribeChannel().sendMulticast(message_To_Send);
		
		setMyScribeID(woDP2PControlChannel.getWoDScribeChannel().getEndpoint().getId().toStringFull());
		
	}
	

	public void send_Leave_Game() throws Exception
	{
		woDP2PControlChannel.getWoDScribeChannel().sendMulticast(
				woDNetProtocolManager.get_LEAVE_GAME(
						woDP2PControlChannel.getWoDScribeChannel().getEndpoint().getId().toStringFull()
						)
				);
	}

	
	public void send_Force_Start() throws Exception
	{
		if (!Iam_Root)
		{
			Exception exception = new Exception("Im not root, cannot send Force Start message.");
			throw exception;
		}
		
		/**
		 * Initialize Wod_Server_RT and add this class as listener
		 */
		woDServerRT = new WoD_Server_RT(
				woDApplicationData.getWoDConfiguration().getRT_Port(), 
				500, 
				0);
		
		
		woDServerRT.add_WoD_Server_RT_Listener(this);
		
		/**
		 * Initialize WoD_RT_Server_Engine
		 */
		woDRTServerEngine = new WoD_RT_Server_Engine(
				woDServerRT, 
				woDServerClientList,
				woDApplicationData.getWoDGame().getMap_Name()
				);
		
		
		/**
		 * Start WoD RT Server
		 */
		woDServerRT.startServer();
		
		/**
		 * Set IDs to clients
		 */
		for (int counter = 0; counter < woDServerClientList.getClients().size(); counter++) {
			woDServerClientList.getClients().get(counter).setCliend_Id(counter);
		}
		
		/**
		 * Send Force Start Message
		 */
		byte[] message_To_Send = woDNetProtocolManager.get_FORCE_START(woDServerClientList, woDApplicationData);
		woDP2PControlChannel.getWoDScribeChannel().sendMulticast(message_To_Send);

	}
	
	
	
	private void check_Start_GAME_COUNT_DOWN() throws Exception
	{
		System.out.println("Check Start game count");
		
		for (WoD_Server_Client woDServerClient : woDServerClientList.getClients()) {
			
			System.out.println(woDServerClient.getUserName() + " " + woDServerClient.isSync());
			
			if (!woDServerClient.isSync())
			{
				return;
			}
		}
		
		/**
		 * Send Count down message
		 */
		long timeStart = System.currentTimeMillis() + 6000;
		byte[] message = woDNetProtocolManager.get_COUNT_DOWN(timeStart); 
		
		woDP2PControlChannel.getWoDScribeChannel().sendMulticast(message);
		
		/**
		 * Change current state to playing state
		 */
		woDApplicationData.getWoDGame().setGame_State(WoD_Game.Game_States.Playing);
		
		
		Runnable runnable = new Runnable() {
			
			//Long sleep = Long.valueOf(2*MapBoard.FPS);
			long sleep = Long.valueOf(2*MapBoard.FPS).longValue();
			
			@Override
			public void run() {
				
				while (RT_Messages_Loop) {
					try {
						Thread.currentThread();
						Thread.sleep(sleep);
						woDRTServerEngine.send_movements();
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}	
				}
			}
		};
		
		RT_Messages_Loop = true;
		thread_RT_Messages = new Thread(runnable);
		thread_RT_Messages.setDaemon(true);
		thread_RT_Messages.start();
		
		
		
	}
	
	@Override
	public void on_WoD_P2P_Control_Channel_Change(WoD_P2P_Control_Channel_Event event) {
		
//		System.out.println("Wod P2P Channel change");
		switch (event.getEvent_Type()) {
		
		case WoD_P2P_Control_Channel_Event.Event_Types.P2P_I_AM_ROOT:
			try {
				Iam_Root = true;
				setMyScribeID(woDP2PControlChannel.getWoDScribeChannel().getEndpoint().getId().toStringFull());
				P2P_ROOT = getMyScribeID();
				manage_Message_CLIENT_P2P_I_AM_ROOT(event);
			} catch (Exception e) {
				e.printStackTrace();
			}
			break;
		
		case WoD_P2P_Control_Channel_Event.Event_Types.P2P_NEW_ROOT:
			Iam_Root = false;
			System.out.println("New ROOT");
			WoD_ScribeContent scribeContent = (WoD_ScribeContent)event.getData();
			P2P_ROOT = scribeContent.getFrom().getId().toStringFull();
			try {
					manage_Message_CLIENT_NEW_ROOT(event);
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			break;
			
		case WoD_P2P_Control_Channel_Event.Event_Types.P2P_NODE_DOWN:
			try {
				manage_Message_CLIENT_P2P_NODE_DOWN(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			break;
		
		case WoD_P2P_Control_Channel_Event.Event_Types.SERVER_JOIN_GAME:
			if (!Iam_Root) {break;}
			try {
				manage_Message_SERVER_JOIN_GAME(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		
		case WoD_P2P_Control_Channel_Event.Event_Types.CLIENT_USER_INFO:
			try {
				manage_Message_CLIENT_NEW_USER(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		
		case WoD_P2P_Control_Channel_Event.Event_Types.CLIENT_GAME_INFO:
			try {
				manage_Message_CLIENT_GAME_INFO(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		
		case WoD_P2P_Control_Channel_Event.Event_Types.CLIENT_LEAVE_GAME:
			try {
				manage_Message_CLIENT_LEAVE_GAME(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		
		case WoD_P2P_Control_Channel_Event.Event_Types.SERVER_SELECT_SIDE:
			if (!Iam_Root) {break;}
			try {
				manage_Message_SERVER_SELECT_TEAM(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
			
		case WoD_P2P_Control_Channel_Event.Event_Types.CLIENT_SELECT_SIDE_INFO:
			try {
				manage_Message_CLIENT_SELECT_SIDE_INFO(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
			
			
		case WoD_P2P_Control_Channel_Event.Event_Types.CLIENT_READY_TO_GO_KO:
			try {
				manage_Message_CLIENT_READY_TO_GO_KO(event);
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println("User ready to go");	
			break;
			
		case WoD_P2P_Control_Channel_Event.Event_Types.CLIENT_READY_TO_GO:
			try {
				manage_Message_CLIENT_READY_TO_GO(event);
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println("User ready to go");	
			break;
		
		
		case WoD_P2P_Control_Channel_Event.Event_Types.CLIENT_SELECT_SIDE_KO:
			System.out.println("Select side KO");
			break;
		
		case WoD_P2P_Control_Channel_Event.Event_Types.CLIENT_SELECT_SIDE_OK:
			System.out.println("Select side OK");
			try {
				manage_Message_CLIENT_SELECT_SIDE_OK(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			break;
		
		case WoD_P2P_Control_Channel_Event.Event_Types.SERVER_READY_TO_GO:
			if (!Iam_Root) {break;}
			try {
				manage_Message_SERVER_READY_TO_GO(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}			
			break;
			
		case WoD_P2P_Control_Channel_Event.Event_Types.SERVER_READY_TO_GO_KO:
			if (!Iam_Root) {break;}
			try {
				manage_Message_SERVER_READY_TO_GO_KO(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}			
			break;
			
		case WoD_P2P_Control_Channel_Event.Event_Types.RT_CLIENT_SYNC_INFO:
			try {
				manage_Message_RT_CLIENT_SYNC_INFO(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
			
		case WoD_P2P_Control_Channel_Event.Event_Types.SERVER_FORCE_START:
			try {
				
				manage_Message_FORCE_START(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
			
		case WoD_P2P_Control_Channel_Event.Event_Types.SERVER_COUNT_DOWN:
			try {
				System.out.println("Server CountDown received");
				manage_Message_COUNT_DOWN(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		
		case WoD_P2P_Control_Channel_Event.Event_Types.CLIENT_SELECT_ROL_INFO:
			try {
				System.out.println("Client Select Rol Info");
				manage_Message_CLIENT_SELECT_ROLE_INFO(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;	
			
		case WoD_P2P_Control_Channel_Event.Event_Types.CLIENT_SELECT_ROL_OK:
			try {
				System.out.println("Client Select Role OK");
				manage_Message_CLIENT_SELECT_ROLE_OK(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
			
		case WoD_P2P_Control_Channel_Event.Event_Types.CLIENT_SELECT_ROL_KO:
			try {
				System.out.println("Client Select Role KO");
				//manage_Message_CLIENT_SELECT_ROLE_OK(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
			
		case WoD_P2P_Control_Channel_Event.Event_Types.SERVER_SELECT_ROL:
			try {
				if (!Iam_Root) {break;}
				System.out.println("Server Select Rol Received");
				manage_Message_SERVER_SELECT_ROL(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
			
		case WoD_P2P_Control_Channel_Event.Event_Types.CHANGE_MAP:
			try {
//				if (!Iam_Root) {break;}
				System.out.println("Change Map Received");
				manage_Message_CHANGE_MAP(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
			
		default:
			break;
		}
		
	}
	
	private void manage_Message_SERVER_JOIN_GAME(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		WoD_Server_Client woDServerClient_Parsed = null;
		
		try {
			woDServerClient_Parsed = woDNetProtocolManager.parse_Join_Game(woDScribeContent.getMessage());
			woDServerClient_Parsed.setScribeNode_ID(woDScribeContent.getFrom().getId().toStringFull());
		} catch (Exception e) {
			throw e;
		}
		
		if (woDClientPeersList == null)
		{
			return;
		}
		
		/**
		 * Check user name
		 */
		if (woDServerClientList.get_positionOfClient_By_UserName(woDServerClient_Parsed.getUserName()) != -1)
		{	
			String message_Info = "User " + woDServerClient_Parsed.getUserName() + " already exists.";
			
			/**
			 * Send Join KO Message
			 */
			try {
				byte[] message_To_Send = woDNetProtocolManager.get_Join_Game_KO(message_Info);
				woDP2PControlChannel.getWoDScribeChannel().sendAnycast(
						woDServerClient_Parsed.getScribeNode_ID(), 
						message_To_Send
						);
				return;
				
			} catch (Exception e) {
				
				throw e;
			}
		}
		
		/**
		 * Add client to client list 
		 */
		woDServerClient_Parsed.setScribeNode_ID(woDScribeContent.getFrom().getId().toStringFull());
		woDServerClientList.add_client(woDServerClient_Parsed);
		
		/**
		 * Send Join OK Message
		 */
		try {
			byte[] message_To_Send = woDNetProtocolManager.get_Join_Game_OK(woDApplicationData, woDServerClient_Parsed);
			woDP2PControlChannel.getWoDScribeChannel().sendAnycast(
					woDServerClient_Parsed.getScribeNode_ID(), 
					message_To_Send
					);
			
		} catch (Exception e) {
			
			throw e;
		}
		
		
		
		
		
		/**
		 * Send New User Info
		 */
		try {
			byte[] message_To_Send = woDNetProtocolManager.get_New_User_Info(woDServerClient_Parsed);
			woDP2PControlChannel.getWoDScribeChannel().sendMulticast(message_To_Send);
		} catch (Exception e) {
			throw e;
		}
		
		
		/**
		 * Send Game Info to new Player
		 */
		try {
			byte[] message_To_Send = woDNetProtocolManager.get_Users_Info(woDServerClientList);
			woDP2PControlChannel.getWoDScribeChannel().sendAnycast(
					woDServerClient_Parsed.getScribeNode_ID(), 
					message_To_Send
					);
		} catch (Exception e) {
			throw e;
		}
		
		
	}
	
	
	private void manage_Message_CLIENT_NEW_USER(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		
		try {
			WoD_Peer woDPeer = woDNetProtocolManager.parse_New_User_Info(woDScribeContent.getMessage());
			
			/**
			 * Throws exeption for duplicate Scribe ID
			 */
			if (woDClientPeersList.get_positionOfPeer_By_ScribeNode_ID(woDPeer.getScribeNode_ID()) != -1)
			{
				Exception exception = new Exception("Wod_Peer with Scribe ID " + woDPeer.getScribeNode_ID() + " already exist.");
				throw exception;
			}
			
			/**
			 * If client username exists replace 
			 * Add if not exists
			 */
			int position = woDClientPeersList.get_positionOfClient_By_UserName(woDPeer.getUserName());
			if (position != -1)
			{
				woDClientPeersList.getWoD_Peers().set(position, woDPeer);
			}
			else
			{
				woDClientPeersList.add_WoD_Peer(woDPeer);
			}
			
			WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
			woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_LIST_MODIFIED);
			notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
			
			if(woDClientPeersList.getWoD_Peers().size()>3)
			{
				for(WoD_Peer peer : woDClientPeersList.getWoD_Peers())
				{
					if(peer.getScribeNode_ID().equals(MyScribeID))
					{
						if(peer.getTeam() == WoD_Game.Game_Teams.Captain_Team)
						{
							woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
							woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_CAN_SELECT_BOTH_ROLS);
							notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
						}
						if(peer.getTeam() == WoD_Game.Game_Teams.Pirates_Team)
						{
							woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
							woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_PIRATE_CAN_SELECT_CAPTAIN);
							notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
						}
						if(peer.getTeam() == -1)
						{
							woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
							woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_CAN_SELECT_BOTH_TEAMS);
							notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
						}
					}
				}
			}
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	private void manage_Message_CLIENT_GAME_INFO(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		P2P_ROOT = woDScribeContent.getFrom().getId().toStringFull();
		try {
			woDClientPeersList = woDNetProtocolManager.parse_Users_Info(woDScribeContent.getMessage());
			
			int counter_Captain_Team = 0;
			for (WoD_Peer woDClient : woDClientPeersList.getWoD_Peers()) {
				if (woDClient.getTeam() == WoD_Game.Game_Teams.Captain_Team)
				{
					counter_Captain_Team++;
				}
			}			
			/**
			 * If there are more than three players and less than two players on captain team then 
			 * join to captain team.
			 */
			if (!(((counter_Captain_Team < 2) && (woDClientPeersList.getWoD_Peers().size() > 3)) ||
				((counter_Captain_Team < 1) && (woDClientPeersList.getWoD_Peers().size() < 4))))
			{
				WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
				woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_CAPTAIN_TEAM_FULL);
				woDP2PPeerEvent.setData(woDScribeContent);
				notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);				
			}else
			{
				WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
				woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_CAPTAIN_TEAM_FREE);
				woDP2PPeerEvent.setData(woDScribeContent);
				notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
			}
			
			
			WoD_P2P_Peer_Event woDP2PPeerEvent_list = new WoD_P2P_Peer_Event(this);
			woDP2PPeerEvent_list.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_LIST_MODIFIED);
			notify_WoD_P2P_Peer_Change(woDP2PPeerEvent_list);
			
			
			WoD_P2P_Peer_Event woDP2PPeerEvent_team = new WoD_P2P_Peer_Event(this);
			woDP2PPeerEvent_team.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_TEAM_CHANGED);
			notify_WoD_P2P_Peer_Change(woDP2PPeerEvent_team);
			
		} catch (Exception e) {
			Exception exception = new Exception("Error trying to manage GAME INFO message. " + e.getMessage());
			throw exception;
		}
	}
	
	
	
	private void manage_Message_CLIENT_P2P_I_AM_ROOT(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		
		
		/**
		 * woDClientPeersList is empty fill with this peer data
		 */
		if (woDClientPeersList.getWoD_Peers().size() == 0)
		{
			WoD_Peer woDPeer = new WoD_Peer();
			
			woDPeer.setUserName(woDApplicationData.getWoDPlayerData().getUserName());
			woDPeer.setScribeNode_ID(
					woDP2PControlChannel.getWoDScribeChannel().getEndpoint().getId().toStringFull()
					);
			woDPeer.setTcp_backup(
					woDApplicationData.getWoDConfiguration().getControl_Port()
					);
			woDPeer.setHostDirection(woDApplicationData.getWoDConfiguration().getHost_Direction());
			woDPeer.setVoice_UDP_Port(woDApplicationData.getWoDConfiguration().getVoice_Port());
			
			woDClientPeersList.add_WoD_Peer(woDPeer);
				
			WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
			woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_LIST_MODIFIED);
			notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
		}
				
		WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
		woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_IS_ROOT);
		notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
		
		woDServerClientList = new WoD_Server_Client_List(woDClientPeersList);
		current_Client_ID = 0;
		
		
		
		manage_I_AM_ROOT_HTTP_UPDATE();
		
	}
	
	private void manage_Message_CLIENT_NEW_ROOT(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		
		WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
		woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_ISNT_ROOT);
		notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
		
	}
	
	private void manage_I_AM_ROOT_HTTP_UPDATE()
	{
		if(woDApplicationData.getMode() == WoD_Application_Data.Mode.WAN)
		{				
			try {
				WoD_InfoPartidasActuales wipa = WoD_HttpMessage.GetCurrentPlayersOnGame(woDApplicationData.getWoDConfiguration().getWeb_Server(), woDApplicationData.getWoDConfiguration().getWeb_Server_Port(), String.valueOf(woDApplicationData.getWoDGame().getID_Game()));
				
				if(Integer.parseInt(wipa.getPlayersNumber())-1<0 && !wipa.getServerStatus().equals("0"))
				{
					ArrayList<String> PlayerNames = new ArrayList<String>();
					
					for (WoD_Peer Peer : woDClientPeersList.getWoD_Peers())
					{
						PlayerNames.add(Peer.getUserName());
						System.out.println("\n PEER NAME: " + Peer.getUserName());
					}
					try {
						System.out.println("\n FROM WOD_GAME_MANAGER: ");
						WoD_HttpMessage.UpdateGame(woDApplicationData.getWoDConfiguration().getWeb_Server(), 
								woDApplicationData.getWoDConfiguration().getWeb_Server_Port(), 
								woDApplicationData.getWoDPlayerData().getUserName(), 
								woDApplicationData.getWoDGame().getServerHost(), 
								String.valueOf(woDApplicationData.getWoDGame().getServer_port()), 
								"0", String.valueOf(woDApplicationData.getWoDGame().getID_Game()), 
								woDApplicationData.getWoDGame().getGame_Title(), PlayerNames);
						
						System.out.println("\n woDAPP: -> GAMEID: " + String.valueOf(woDApplicationData.getWoDGame().getID_Game()));
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						//show_Error("HTTP Connection Error.");
					}
				}else if (!wipa.getServerStatus().equals("0"))
				{
					ArrayList<String> PlayerNames = new ArrayList<String>();
					for (WoD_Peer Peer : woDClientPeersList.getWoD_Peers())
					{
						PlayerNames.add(Peer.getUserName());
						System.out.println("\n PEER NAME: " + Peer.getUserName());
					}
					try {
						WoD_HttpMessage.UpdateGame(woDApplicationData.getWoDConfiguration().getWeb_Server(), 
								woDApplicationData.getWoDConfiguration().getWeb_Server_Port(), 
								woDApplicationData.getWoDPlayerData().getUserName(), 
								woDApplicationData.getWoDGame().getServerHost(), 
								String.valueOf(woDApplicationData.getWoDGame().getServer_port()), 
								"1", String.valueOf(woDApplicationData.getWoDGame().getID_Game()), 
								woDApplicationData.getWoDGame().getGame_Title(), PlayerNames);
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						//show_Error("HTTP Connection Error.");
					//	e.printStackTrace();
					}
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				//show_Error("HTTP Connection Error.");ç
				e.printStackTrace();
			}
			
		}
	}
	
	
	private void manage_Message_CLIENT_P2P_NODE_DOWN(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
	
		String peer_ID = woDNetProtocolManager.parse_NODE_DOWN(woDScribeContent.getMessage());
	
		/**
		 * Remove from peer list
		 */
		woDClientPeersList.remove_WoD_Peer_By_P2P_ID(peer_ID);
		
		if (Iam_Root)
		{
			woDServerClientList.remove_Client_By_P2P_ID(peer_ID);
		}
		
		WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
		woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_LIST_MODIFIED);
		notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
		
		WoD_P2P_Peer_Event woDP2PPeerEvent_team = new WoD_P2P_Peer_Event(this);
		woDP2PPeerEvent_team.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_TEAM_CHANGED);
		notify_WoD_P2P_Peer_Change(woDP2PPeerEvent_team);
		
	}
	
	private void manage_Message_CLIENT_LEAVE_GAME(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		
		String peer_ID = woDNetProtocolManager.parse_LEAVE_GAME(woDScribeContent.getMessage());
		
		/**
		 * Remove from peer list
		 */
		woDClientPeersList.remove_WoD_Peer_By_P2P_ID(peer_ID);
		
		if (Iam_Root)
		{
			woDServerClientList.remove_Client_By_P2P_ID(peer_ID);
		}
		
		WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
		woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_LIST_MODIFIED);
		notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
		
		WoD_P2P_Peer_Event woDP2PPeerEvent_team = new WoD_P2P_Peer_Event(this);
		woDP2PPeerEvent_team.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_TEAM_CHANGED);
		notify_WoD_P2P_Peer_Change(woDP2PPeerEvent_team);
	}
	
	
	
	private void manage_Message_SERVER_SELECT_TEAM(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		try {
			/**
			 * Inspect Team Code
			 */
			String TEAM_CODE = woDNetProtocolManager.parse_SELECT_SIDE(woDScribeContent.getMessage());
			String P2P_ID = woDScribeContent.getFrom().getId().toStringFull();
			
			
			int position = woDServerClientList.get_positionOfClient_By_ScribeNode_ID(P2P_ID);
			if (position == -1)
			{
				Exception exception = new Exception("Unknown P2P_ID " + P2P_ID);
				throw exception;
			}
			
			/**
			 * PIRATE TEAM CODE
			 */
			if (TEAM_CODE.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Side_OPTION_PiratesTeam))
			{

				woDServerClientList.getClients().get(position).setTeam(WoD_Game.Game_Teams.Pirates_Team);
				woDServerClientList.getClients().get(position).setROL(WoD_Game.Game_Rols.Default);

				try {
					/**
					 * Send Select side OK Info to Player
					 */
					byte[] message_AnyCast = woDNetProtocolManager.get_SELECT_SIDE_OK(
							TEAM_CODE);

					woDP2PControlChannel.getWoDScribeChannel().sendAnycast(
							P2P_ID, 
							message_AnyCast
					);

					/**
					 * Send chage Team Info to all
					 */
					byte[] message_MultiCast = woDNetProtocolManager.get_SELECT_SIDE_INFO(P2P_ID, TEAM_CODE);
					woDP2PControlChannel.getWoDScribeChannel().sendMulticast(message_MultiCast);


				} catch (Exception e) {
					throw e;
				}

			}
			
			/**
			 * CAPTAIN TEAM CODE
			 */
			else if (TEAM_CODE.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Side_OPTION_GoodTeam))
			{
				/**
				 * Count Captain team members
				 */
				int counter_Captain_Team = 0;
				for (WoD_Server_Client woDServerClient : woDServerClientList.getClients()) {
					if (woDServerClient.getTeam() == WoD_Game.Game_Teams.Captain_Team)
					{
						counter_Captain_Team++;
					}
				}
				
				/**
				 * If there are more than three players and less than two players on captain team then 
				 * join to captain team.
				 */
				if (((counter_Captain_Team < 2) && (woDServerClientList.getClients().size() > 3)) ||
					((counter_Captain_Team < 1) && (woDServerClientList.getClients().size() < 4)))
				{
					woDServerClientList.getClients().get(position).setTeam(WoD_Game.Game_Teams.Captain_Team);
					woDServerClientList.getClients().get(position).setROL(WoD_Game.Game_Rols.Default);
					
					/**
					 * Send Select side OK Info to Player
					 */
					byte[] message_AnyCast = woDNetProtocolManager.get_SELECT_SIDE_OK(
							TEAM_CODE);
					
					woDP2PControlChannel.getWoDScribeChannel().sendAnycast(
							P2P_ID, 
							message_AnyCast
							);
					
					/**
					 * Send chage Team Info to all
					 */
					byte[] message_MultiCast = woDNetProtocolManager.get_SELECT_SIDE_INFO(P2P_ID, TEAM_CODE);
					woDP2PControlChannel.getWoDScribeChannel().sendMulticast(message_MultiCast);
				}
				
				/**
				 * Other combinations are not possible 
				 */
				else
				{
					/**
					 * Send Select side KO Info to Player
					 */
					byte[] message_AnyCast = woDNetProtocolManager.get_SELECT_SIDE_KO(
							"Captain Team is full");
					
					woDP2PControlChannel.getWoDScribeChannel().sendAnycast(
							P2P_ID, 
							message_AnyCast
							);
					
				}
			
				
			}
			
		} catch (Exception e) {
			Exception exception = new Exception("Error trying to manage SELECT TEAM message. " + e.getMessage());
			throw exception;
		}
	}
	
	private void manage_Message_SERVER_SELECT_ROL(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		try {
			/**
			 * Inspect Team Code
			 */
			String ROL_CODE = woDNetProtocolManager.parse_SELECT_ROL(woDScribeContent.getMessage());
			String P2P_ID = woDScribeContent.getFrom().getId().toStringFull();
			
			
			int position = woDServerClientList.get_positionOfClient_By_ScribeNode_ID(P2P_ID);
			if (position == -1)
			{
				Exception exception = new Exception("Unknown P2P_ID " + P2P_ID);
				throw exception;
			}
			
			if (ROL_CODE.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol_OPTION_Captain))
			{
				/**
				 * Check if there's captain role selected
				 */
				boolean check_Captain_Role = false;
				for (WoD_Server_Client woDServerClient : woDServerClientList.getClients()) {
					if (woDServerClient.getTeam() == WoD_Game.Game_Teams.Captain_Team &&
							woDServerClient.getROL() == WoD_Game.Game_Rols.Captain)
					{
						check_Captain_Role = true;
						break;
					}
				}
				
				/**
				 * If no Captain_Role is selected assign it to the player.
				 */
				if (check_Captain_Role == false)
				{
					woDServerClientList.getClients().get(position).setROL(WoD_Game.Game_Rols.Captain);
					
					/**
					 * Send Select role OK Info to Player
					 */
					byte[] message_AnyCast = woDNetProtocolManager.get_SELECT_ROLE_OK(
							ROL_CODE);
					
					woDP2PControlChannel.getWoDScribeChannel().sendAnycast(
							P2P_ID, 
							message_AnyCast
							);
					
					/**
					 * Send Select Role to all
					 */
					byte[] message_MultiCast = woDNetProtocolManager.get_SELECT_ROLE_INFO(P2P_ID, ROL_CODE);
					woDP2PControlChannel.getWoDScribeChannel().sendMulticast(message_MultiCast);
				}
				
				/**
				 * Other combinations are not possible 
				 */
				else
				{
					/**
					 * Send Select side KO Info to Player
					 */
					byte[] message_AnyCast = woDNetProtocolManager.get_SELECT_ROLE_KO(
							"No Captain Role is selected");
					
					woDP2PControlChannel.getWoDScribeChannel().sendAnycast(
							P2P_ID, 
							message_AnyCast
							);
					
				}
			
				
			}else if (ROL_CODE.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol_OPTION_Maiden))
			{
				/**
				 * Check if there's maiden role selected
				 */
				boolean check_Maiden_Role = false;
				int counter_Captain_Team = 0;
				for (WoD_Server_Client woDServerClient : woDServerClientList.getClients()) {
					if (woDServerClient.getTeam() == WoD_Game.Game_Teams.Captain_Team &&
							woDServerClient.getROL() == WoD_Game.Game_Rols.Princess)
					{
						check_Maiden_Role = true;
					}
					if (woDServerClient.getTeam() == WoD_Game.Game_Teams.Captain_Team)
					{
						counter_Captain_Team++;
					}
				}
				
				/**
				 * If no Maiden_Role is selected assign it to the player.
				 */
				if (check_Maiden_Role == false && counter_Captain_Team > 1)
				{
					woDServerClientList.getClients().get(position).setROL(WoD_Game.Game_Rols.Princess);
					
					/**
					 * Send Select role OK Info to Player
					 */
					byte[] message_AnyCast = woDNetProtocolManager.get_SELECT_ROLE_OK(
							ROL_CODE);
					
					woDP2PControlChannel.getWoDScribeChannel().sendAnycast(
							P2P_ID, 
							message_AnyCast
							);
					
					/**
					 * Send Select Role to all
					 */
					byte[] message_MultiCast = woDNetProtocolManager.get_SELECT_ROLE_INFO(P2P_ID, ROL_CODE);
					woDP2PControlChannel.getWoDScribeChannel().sendMulticast(message_MultiCast);
				}
				
				/**
				 * Other combinations are not possible 
				 */
				else
				{
					/**
					 * Send Select side KO Info to Player
					 */
					byte[] message_AnyCast = woDNetProtocolManager.get_SELECT_ROLE_KO(
							"Not role selected");
					
					woDP2PControlChannel.getWoDScribeChannel().sendAnycast(
							P2P_ID, 
							message_AnyCast
							);
					
				}
			}
			
		} catch (Exception e) {
			Exception exception = new Exception("Error trying to manage SELECT ROL message. " + e.getMessage());
			throw exception;
		}
	}	
	
	private void manage_Message_CLIENT_SELECT_SIDE_INFO(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		try {
			WoD_Peer woDPeer = woDNetProtocolManager.parse_SELECT_SIDE_INFO(woDScribeContent.getMessage());
			int position = woDClientPeersList.get_positionOfPeer_By_ScribeNode_ID(woDPeer.getScribeNode_ID());
			if (position == -1)
			{
				Exception exception = new Exception("Peer with P2P_ID " + woDPeer.getScribeNode_ID() + " not found.");
				throw exception;
			}
			woDClientPeersList.getWoD_Peers().get(position).setTeam(woDPeer.getTeam());
			woDClientPeersList.getWoD_Peers().get(position).setROL(WoD_Game.Game_Rols.Default);
			
			int counter_Captain_Team = 0;
			boolean im_captain = false;
			for (WoD_Peer woDClient : woDClientPeersList.getWoD_Peers()) {
				if (woDClient.getTeam() == WoD_Game.Game_Teams.Captain_Team)
				{
					counter_Captain_Team++;
				}
				if (woDClient.getScribeNode_ID() == MyScribeID 
						&& woDClient.getTeam() == WoD_Game.Game_Teams.Captain_Team)
				{
					im_captain = true;
				}
			}	
						
			if (counter_Captain_Team>1)
			{
				WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
				woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_CAN_SELECT_BOTH_ROLS);
				woDP2PPeerEvent.setData(woDScribeContent);
				notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
			}else
			{
				WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
				woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_ONLY_CAN_SELECT_CAPTAIN);
				woDP2PPeerEvent.setData(woDScribeContent);
				notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
			}
			
			/**
			 * If there are more than three players and less than two players on captain team then 
			 * join to captain team.
			 */
			if (!(((counter_Captain_Team < 2) && (woDClientPeersList.getWoD_Peers().size() > 3)) ||
				((counter_Captain_Team < 1) && (woDClientPeersList.getWoD_Peers().size() < 4))))
			{
				WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
				woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_CAPTAIN_TEAM_FULL);
				woDP2PPeerEvent.setData(woDScribeContent);
				notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);				
			}else
			{
				WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
				woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_CAPTAIN_TEAM_FREE);
				woDP2PPeerEvent.setData(woDScribeContent);
				notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
			}
			
			
			
			WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
			woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_TEAM_CHANGED);
			woDP2PPeerEvent.setData(woDScribeContent);
			notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
			
		} catch (Exception e) {
			Exception exception = new Exception("Error trying to manage SIDO INFO message. " + e.getMessage());
			throw exception;
		}
	}
	
	private void manage_Message_CLIENT_SELECT_ROLE_INFO(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		try {
			WoD_Peer woDPeer = woDNetProtocolManager.parse_SELECT_ROLE_INFO(woDScribeContent.getMessage());
			int position = woDClientPeersList.get_positionOfPeer_By_ScribeNode_ID(woDPeer.getScribeNode_ID());
			if (position == -1)
			{
				Exception exception = new Exception("Peer with P2P_ID " + woDPeer.getScribeNode_ID() + " not found.");
				throw exception;
			}
			woDClientPeersList.getWoD_Peers().get(position).setROL(woDPeer.getROL());
						
			WoD_P2P_Peer_Event woDP2PPeerEvent = new WoD_P2P_Peer_Event(this);
			woDP2PPeerEvent.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_TEAM_CHANGED);
			woDP2PPeerEvent.setData(woDScribeContent);
			notify_WoD_P2P_Peer_Change(woDP2PPeerEvent);
			
		} catch (Exception e) {
			Exception exception = new Exception("Error trying to manage GAME INFO message. " + e.getMessage());
			throw exception;
		}
	}
		
	private void manage_Message_CLIENT_SELECT_SIDE_OK(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();

		String TEAM_CODE = woDNetProtocolManager.parse_SELECT_SIDE_OK(woDScribeContent.getMessage());

		if (TEAM_CODE.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Side_OPTION_GoodTeam))
		{
			WoD_P2P_Peer_Event woDP2PPeerEvent_team = new WoD_P2P_Peer_Event(this);
			woDP2PPeerEvent_team.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_CAPTAIN_TEAM);
			notify_WoD_P2P_Peer_Change(woDP2PPeerEvent_team);
			
			int counter_Captain_Team = 0;
			boolean im_captain = false;
			for (WoD_Peer woDClient : woDClientPeersList.getWoD_Peers()) {
				if (woDClient.getTeam() == WoD_Game.Game_Teams.Captain_Team)
				{
					counter_Captain_Team++;
				}
				if (woDClient.getScribeNode_ID() == MyScribeID 
						&& woDClient.getTeam() == WoD_Game.Game_Teams.Captain_Team)
				{
					im_captain = true;
				}
			}

			if (woDClientPeersList.getWoD_Peers().size()<3 && counter_Captain_Team == 1)
			{
				woDP2PPeerEvent_team = new WoD_P2P_Peer_Event(this);
				woDP2PPeerEvent_team.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_ONLY_CAN_SELECT_CAPTAIN);
				notify_WoD_P2P_Peer_Change(woDP2PPeerEvent_team);		

			}else
			{
				woDP2PPeerEvent_team = new WoD_P2P_Peer_Event(this);
				woDP2PPeerEvent_team.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_CAN_SELECT_BOTH_ROLS);
				notify_WoD_P2P_Peer_Change(woDP2PPeerEvent_team);
			} 
			
//			if (woDClientPeersList.getWoD_Peers().size()<3)
			
		}else if (TEAM_CODE.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Side_OPTION_PiratesTeam))
		{
			WoD_P2P_Peer_Event woDP2PPeerEvent_team2 = new WoD_P2P_Peer_Event(this);
			woDP2PPeerEvent_team2.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_PIRATES_TEAM);
			notify_WoD_P2P_Peer_Change(woDP2PPeerEvent_team2);
		}
		else
		{
			Exception exception = new Exception("Unknown game team option " + TEAM_CODE);
			throw exception;
		}
		
	}
	
	private void manage_Message_CLIENT_SELECT_ROLE_OK(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		
		String ROLE_CODE = woDNetProtocolManager.parse_SELECT_ROLE_OK(woDScribeContent.getMessage());
		
		if (ROLE_CODE.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol_OPTION_Captain))
		{
			WoD_P2P_Peer_Event woDP2PPeerEvent_team = new WoD_P2P_Peer_Event(this);
			woDP2PPeerEvent_team.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_ROL_CAPTAIN);
			notify_WoD_P2P_Peer_Change(woDP2PPeerEvent_team);
		} 
		else if (ROLE_CODE.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol_OPTION_Maiden))
		{
			WoD_P2P_Peer_Event woDP2PPeerEvent_team = new WoD_P2P_Peer_Event(this);
			woDP2PPeerEvent_team.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_ROL_MAIDEN);
			notify_WoD_P2P_Peer_Change(woDP2PPeerEvent_team);
		}
		else
		{
			Exception exception = new Exception("Unknown game team option " + ROLE_CODE);
			throw exception;
		}
	}
	
    private void manage_Message_CHANGE_MAP(WoD_P2P_Control_Channel_Event event) throws Exception
    {
    	WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		try {
			String mapName = woDNetProtocolManager.parse_SELECT_MAP(woDScribeContent.getMessage());
			
			woDApplicationData.getWoDGame().setMap_Name(mapName);
			
			System.out.println("PEERS MAP SELECTED: " + mapName);
			
		} catch (Exception e) {
			Exception exception = new Exception("Error trying to manage SIDO INFO message. " + e.getMessage());
			throw exception;
		}
    }
	
    private void manage_Message_SERVER_READY_TO_GO(WoD_P2P_Control_Channel_Event event) throws Exception
    {
            WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
            try {
                    /**
                     * Get scribe id
                     */
            	
                    String P2P_ID = woDScribeContent.getFrom().getId().toStringFull(); 
                    	//woDNetProtocolManager.parse_READY_TO_PLAY(woDScribeContent.getMessage());
                    
                    int position = woDServerClientList.get_positionOfClient_By_ScribeNode_ID(P2P_ID);
                    if (position == -1)
                    {
                            Exception exception = new Exception("Unknown P2P_ID " + P2P_ID);
                            throw exception;
                    }
                    
                    //woDServerClientList.getClients().get(position).setReady(true);
                    int counter_Captain_Team = 0;
                    
                    for (WoD_Peer woDClient : woDClientPeersList.getWoD_Peers()) 
                    {
                    	if(woDClient.getTeam() == WoD_Game.Game_Teams.Captain_Team)
                    	{
                    		counter_Captain_Team++;
                    	}                   	
                    }
                    
                    try {
                            /**
                             * Send new ready user to members
                             */
                    	
                    	boolean correcte = false;
            			for (WoD_Peer woDClient : woDClientPeersList.getWoD_Peers()) {
            				if (woDClient.getScribeNode_ID().equals(P2P_ID))
            				{
            					if(woDClient.getTeam() == WoD_Game.Game_Teams.Pirates_Team)
            					{
            						correcte = true;
            					}
            					else if(woDClient.getTeam() == WoD_Game.Game_Teams.Captain_Team)
            					{
            						if((woDClient.getROL() == WoD_Game.Game_Rols.Captain) || 
            								(woDClient.getROL() == WoD_Game.Game_Rols.Princess && counter_Captain_Team > 1))            								
            						{
            							correcte = true;
            						}           						
            						else
            						{
            							correcte = false;
            						}
            					}
            				}            				         				
            			}
                    	
            			//if((counter_Captain_Team>0 && counter_Captain_Team<=2)&&(counter_Pirate_Team>0))
            			
            			byte[] message_MultiCast = null;
            			if(correcte == true)
            			{
            				woDServerClientList.getClients().get(position).setReadyToGo(true);
            				message_MultiCast = woDNetProtocolManager.get_READY_TO_PLAY_OK(P2P_ID);
            				woDP2PControlChannel.getWoDScribeChannel().sendMulticast(message_MultiCast);
            			}
            			
//            			else
//            			{
//            				message_MultiCast = woDNetProtocolManager.get_NOT_READY_TO_PLAY(P2P_ID);
//                        	woDP2PControlChannel.getWoDScribeChannel().sendMulticast(message_MultiCast);
//            			}
                    	
                    	
                    
                    } catch (Exception e) {
                            throw e;
                    }
                                            
                    /**
                     * Count Ready members
                     */
                  int i = 0;
                  for (WoD_Server_Client woDServerClient : woDServerClientList.getClients()) {
                          if (woDServerClient.isReadyToGo())
                          {
                                  i++;
                          }
                  }
                    
                  if(i-1==woDServerClientList.getClients().size())
                  {
                	  send_Force_Start();
                  }
            
            } catch (Exception e) {
                    Exception exception = new Exception("Error trying to manage READY_TO_GO message. " + e.getMessage());
                    throw exception;
            }
    }
		
    private void manage_Message_SERVER_READY_TO_GO_KO(WoD_P2P_Control_Channel_Event event) throws Exception
    {
            WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
            try {
                    /**
                     * Get scribe id
                     */
            	
                    String P2P_ID = woDScribeContent.getFrom().getId().toStringFull(); 
                    	//woDNetProtocolManager.parse_READY_TO_PLAY(woDScribeContent.getMessage());
                    
                    int position = woDServerClientList.get_positionOfClient_By_ScribeNode_ID(P2P_ID);
                    if (position == -1)
                    {
                            Exception exception = new Exception("Unknown P2P_ID " + P2P_ID);
                            throw exception;
                    }
                    
                    //woDServerClientList.getClients().get(position).setReady(true);
                    
                    try {
                            /**
                             * Send new ready user to members
                             */
                    	

                    	woDServerClientList.getClients().get(position).setReadyToGo(false);

                    	byte[] message_MultiCast = woDNetProtocolManager.get_NOT_READY_TO_PLAY(P2P_ID);
                    	woDP2PControlChannel.getWoDScribeChannel().sendMulticast(message_MultiCast);
                    
                    } catch (Exception e) {
                            throw e;
                    }
                                            
                    /**
                     * Count Ready members
                     */
//                  int i = 0;
//                  for (WoD_Server_Client woDServerClient : woDServerClientList.getClients()) {
//                          if (woDServerClient.isReady())
//                          {
//                                  i++;
//                          }
//                  }
                    
//                  if(i==woDServerClientList.getClients().size())
//                  {
//                          //TODOS LOS MIEMBROS LISTOS, LANZAR EVENTO?
//                  }
            
            } catch (Exception e) {
                    Exception exception = new Exception("Error trying to manage READY_TO_GO message. " + e.getMessage());
                    throw exception;
            }
    }
	
	private void manage_Message_FORCE_START(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent) event.getData();
		try {
			woDClientPeersList = woDNetProtocolManager.parse_FORCE_START(woDScribeContent.getMessage(), woDApplicationData);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return;
		}
		
		/**
		 * Start WoD_Client_RT and add this class as listener
		 */
		woDClientRT = new WoD_Client_RT(
				0, 
				500, 
				0);
		
		
		woDClientRT.add_WoD_Client_RT_Listener(this);
		
		
		/**
		 * Set my RT ID
		 */
		int position = woDClientPeersList.get_positionOfPeer_By_ScribeNode_ID(MyScribeID);
		if (position == -1)
		{
			Exception exception = new Exception("User with Scribe ID " + MyScribeID + " not found");
			throw exception;
		}
		current_Client_ID = woDClientPeersList.getWoD_Peers().get(position).getCliend_Id();
		
		
		try {
			woDClientRT.startClient();

			
			/**
			 * NTP Client runnable
			 */
			Runnable runnable_NTP_Client = new Runnable() {

				@Override
				public void run() {
					while (NTP_Loop) {


						WoD_RT_NTP_Message woDNTPMessage = new WoD_RT_NTP_Message();
						woDNTPMessage.setID(current_Client_ID);

						try {
							
							Thread.currentThread();
							Thread.sleep(2000);
							woDNTPMessage.setTS_CS(System.currentTimeMillis());
							byte[] message = woDNetProtocolManager.get_RT_NTP_CLIENT_MESSAGE(woDNTPMessage);
							woDClientRT.sendMessage(
									woDApplicationData.getWoDGame().getServerHost(), 
									woDApplicationData.getWoDGame().getServer_RT_Port(), 
									message);
							
//							System.out.println("NTP Query Message sent to " + woDApplicationData.getWoDGame().getServerHost() + ":" + woDApplicationData.getWoDGame().getServer_RT_Port());
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
							NTP_Loop = false;
						}
					}

				}
			};

			
			/**
			 * Start NTP Client
			 */
			NTP_Loop = true;
			thread_NTP_CLIENT = new Thread(runnable_NTP_Client);
			thread_NTP_CLIENT.setDaemon(true);
			thread_NTP_CLIENT.start();



		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	private void manage_Message_CLIENT_READY_TO_GO(WoD_P2P_Control_Channel_Event event) throws Exception
	{
//		System.out.println("WoD_P2P_Peer: manage_Message_CLIENT_READY_TO_GO()");
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		try {
			/**
			 * Get scribe id
			 */
			String P2P_ID = woDNetProtocolManager.parse_READY_TO_PLAY_OK(woDScribeContent.getMessage());
			
			try {
				/**
				 * Send new ready user to members
				 */
				System.out.println("\n" + P2P_ID + "is ready to play");
				//getWoDReadyClients().add(P2P_ID);
				
//				Composite_Options_Event optionsEvent = new Composite_Options_Event(compositeGameRoom.get_Composite_Options());
//				optionsEvent.setEventType(Composite_Options_Event.Event_Types.READY_TO_PLAY_OK);
//				
//				compositeGameRoom.get_Composite_Options().fire_Composite_Options_Event(optionsEvent);
				
				//compositeGameRoom.getPeerList_NEW().paint_Table(woDP2PPeer.getWoDClientPeersList().getWoD_Peers());
				
				int position = woDClientPeersList.get_positionOfPeer_By_ScribeNode_ID(P2P_ID);
				if (position == -1)
				{
					throw new Exception("User " + P2P_ID + " not found");
				}
				
				woDClientPeersList.getWoD_Peers().get(position).setReadyToGo(true);
				
				WoD_P2P_Peer_Event woDP2PPeerEvent_list = new WoD_P2P_Peer_Event(this);
				woDP2PPeerEvent_list.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_LIST_MODIFIED);
				notify_WoD_P2P_Peer_Change(woDP2PPeerEvent_list);
				
			
				
				
			} catch (Exception e) {
				throw e;
			}
		
		} catch (Exception e) {
			Exception exception = new Exception("Error trying to manage SELECT READY TO GO message. " + e.getMessage());
			throw exception;
		}
	}
	
	private void manage_Message_CLIENT_READY_TO_GO_KO(WoD_P2P_Control_Channel_Event event) throws Exception
	{
//		System.out.println("WoD_P2P_Peer: manage_Message_CLIENT_READY_TO_GO_KO()");
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		try {
			/**
			 * Get scribe id
			 */
			String P2P_ID = woDNetProtocolManager.parse_NOT_READY_TO_PLAY(woDScribeContent.getMessage());
			
			try {
				/**
				 * Send new ready user to members
				 */
//				System.out.println("\n" + P2P_ID + "is not ready to play");
				
				//getWoDReadyClients().add(P2P_ID);
				
//				Composite_Options_Event optionsEvent = new Composite_Options_Event(compositeGameRoom.get_Composite_Options());
//				optionsEvent.setEventType(Composite_Options_Event.Event_Types.READY_TO_PLAY_OK);
//				
//				compositeGameRoom.get_Composite_Options().fire_Composite_Options_Event(optionsEvent);
				
				//compositeGameRoom.getPeerList_NEW().paint_Table(woDP2PPeer.getWoDClientPeersList().getWoD_Peers());
				
				int position = woDClientPeersList.get_positionOfPeer_By_ScribeNode_ID(P2P_ID);
				if (position == -1)
				{
					throw new Exception("User " + P2P_ID + " not found");
				}
				
				woDClientPeersList.getWoD_Peers().get(position).setReadyToGo(false);
				
				WoD_P2P_Peer_Event woDP2PPeerEvent_list = new WoD_P2P_Peer_Event(this);
				woDP2PPeerEvent_list.setEvent_Type(WoD_P2P_Peer_Event.Event_Types.PEER_LIST_MODIFIED);
				notify_WoD_P2P_Peer_Change(woDP2PPeerEvent_list);							
			} catch (Exception e) {
				throw e;
			}
		
		} catch (Exception e) {
			Exception exception = new Exception("Error trying to manage SELECT READY TO GO KO message. " + e.getMessage());
			throw exception;
		}
	}
	
	private void manage_Message_COUNT_DOWN(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		System.out.println("WoD_P2P_Peer: manage_Message_CLIENT_READY_TO_GO_KO()");
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		
		final long ts_Start_Game = woDNetProtocolManager.parse_COUNT_DOWN(woDScribeContent.getMessage());
		
		Runnable runnable = new Runnable() {
			
			@Override
			public void run() {
				long wait_Time = Long.valueOf(ts_Start_Game - System.currentTimeMillis() - offset);
				System.out.println("La partida empezará en " + wait_Time + " ms");
				try {
					Thread.currentThread();
					Thread.sleep(wait_Time);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return;
				}
				System.out.println("La partida empieza ahora " + System.currentTimeMillis() + offset);
				
			}
		};
		
		Thread thread = new Thread(runnable);
		thread.setDaemon(true);
		thread.start();
		
		
//		shellRTGame = new Shell_RT_Game(
//				get_My_WoD_Peer(),
//				woDClientRT,
//				woDClientPeersList, 
//				ts_Start_Game, Display.getCurrent());
//		
//		woDClientRT.add_WoD_Client_RT_Listener(shellRTGame.getCompositeRTGame().get_Map_Board());
//		shellRTGame.getCompositeRTGame().get_Map_Board().add_WoD_MapBoard_Listener(this);
//		
//		
//		shellRTGame.execute();
		
		
	}
	
	@Override
	public void notify_Event_WoD_Client_RTChannel(WoD_Client_RT_Event event) {
		switch (event.getEvent_Type()) {
		case WoD_Client_RT_Event.GAME_NTP:
			manage_Message_RT_Client_NTP(event);
			break;
		
		default:
			break;
		}
		
	}
	
	
	
	private void manage_Message_RT_Server_NTP(WoD_Server_RT_Event event) throws Exception
	{
		WoD_RT_NTP_Message woDNTPMessage = null;
		DatagramPacket datagramPacket = (DatagramPacket)event.getData();
		
		//System.out.println("NTP Query received from " + datagramPacket.getAddress().getHostAddress() + ":" + datagramPacket.getPort());
		
		woDNTPMessage = woDNetProtocolManager.parse_RT_NTP_CLIENT_MESSAGE(datagramPacket.getData());
		woDNTPMessage.setTS_SR(System.currentTimeMillis());
		
		/**
		 * Yield current thread
		 */
		Thread.currentThread();
		Thread.yield();
	
		/**
		 * Find user by ID
		 */
		int position = woDServerClientList.get_PositionOfClient_By_ID(woDNTPMessage.getID());
		if (position == -1)
		{
			Exception exception = new Exception("WoD client with ID " + woDNTPMessage.getID() + " not found.");
			throw exception;
		}
		
		/**
		 * Set udp port to client
		 */
		woDServerClientList.getClients().get(position).setUdp_port(datagramPacket.getPort());
		WoD_Server_Client woDServerClient = woDServerClientList.getClients().get(position);
		
	
		woDNTPMessage.setTS_SS(System.currentTimeMillis());
	
		byte[] message = woDNetProtocolManager.get_RT_NTP_SERVER_MESSAGE(woDNTPMessage);
		woDServerRT.send_Message_To_Client(woDServerClient, message);
		
	
	}

	@Override
	public void notify_Event_WoD_Server_RTChannel(WoD_Server_RT_Event event) {
		switch (event.getEvent_Type()) {
		case WoD_Server_RT_Event.GAME_NTP:
			
			try {
//				System.out.println("Received NTP Query");
				manage_Message_RT_Server_NTP(event);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			break;

		default:
			break;
		}
		
	}
	

	
	

	private void manage_Message_RT_Client_NTP(WoD_Client_RT_Event event)
	{

		WoD_RT_NTP_Message woDNTPMessage = null;
		DatagramPacket datagramPacket = (DatagramPacket)event.getData();

		try {
			woDNTPMessage = woDNetProtocolManager.parse_RT_NTP_SERVER_MESSAGE(datagramPacket.getData());

			long received_Time = System.currentTimeMillis();
			//int rtt =  Long.valueOf((received_Time - woDNTPMessage.getTS_SR()) - (woDNTPMessage.getTS_CS() - woDNTPMessage.getTS_CR())).intValue();
			int rtt =  Long.valueOf((received_Time - woDNTPMessage.getTS_CS()) - (woDNTPMessage.getTS_SR() - woDNTPMessage.getTS_SR())).intValue();
			int delay = rtt / 2;

			offset = Long.valueOf(received_Time - woDNTPMessage.getTS_SR()).intValue() - delay;
			offset = -offset;

			System.out.println("OffSet: " + offset);
			

			if (Iam_Root)
			{
				
				/**
				 * Search client
				 */
				int position = woDServerClientList.get_positionOfClient_By_ScribeNode_ID(MyScribeID);
				if (position == -1)
				{
					Exception exception = new Exception("Wod client with P2P ID " + MyScribeID + " not found.");
					throw exception;

				}

				
				
				/**
				 * Set client delay and Sync flag
				 */
				woDServerClientList.getClients().get(position).setDelay(delay);
				woDServerClientList.getClients().get(position).setSync(true);
				

				if (woDApplicationData.getWoDGame().getGame_State() != WoD_Game.Game_States.Playing)
				{
					check_Start_GAME_COUNT_DOWN();	
				}
				
			}
			else
			{
				byte[] message = woDNetProtocolManager.get_RT_CLIENT_SYNC_INFO(delay);
				woDP2PControlChannel.getWoDScribeChannel().sendAnycast(
						P2P_ROOT, 
						message);
			}





			//			int rtt = Long.valueOf((received_time - server_sendTime) - (client_sent_time - client_received_time)).intValue();
			//			int delay = rtt / 2;
			//			int offSet = Long.valueOf(client_received_time - server_sendTime).intValue() - delay;
			//			
			//			client.setDelay(delay);
			//			client.setOffset(offSet);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private void manage_Message_RT_CLIENT_SYNC_INFO(WoD_P2P_Control_Channel_Event event) throws Exception
	{
		//System.out.println("Client Sync received");
		
		WoD_ScribeContent woDScribeContent = (WoD_ScribeContent)event.getData();
		
		String P2P_ID = woDScribeContent.getFrom().getId().toStringFull();
		
		/**
		 * Search client
		 */
		int position = woDServerClientList.get_positionOfClient_By_ScribeNode_ID(P2P_ID);
		if (position == -1)
		{
			Exception exception = new Exception("Wod client with P2P ID " + P2P_ID + " not found.");
			throw exception;
			
		}
		
		/**
		 * Set client delay and Sync flag
		 */
		int delay = woDNetProtocolManager.parse_RT_CLIENT_SYNC_INFO(woDScribeContent.getMessage());
		woDServerClientList.getClients().get(position).setDelay(delay);
		woDServerClientList.getClients().get(position).setSync(true);
		
//		System.out.println("Sync for client " + woDServerClientList.getClients().get(position).getUserName() + " " + woDServerClientList.getClients().get(position).isSync());
		
		/**
		 * If still not in playing state check start condition
		 */
		if (woDApplicationData.getWoDGame().getGame_State() != WoD_Game.Game_States.Playing)
		{
			check_Start_GAME_COUNT_DOWN();	
		}
		
		
	}
	
//	/**
//	 * Shows error message
//	 * @param error
//	 */
//	private void show_Error(String error)
//	{
//		MessageBox messageBox = new MessageBox(compositeGameRoom.getShell(), SWT.ICON_ERROR | SWT.OK);
//		messageBox.setText("Error");
//		messageBox.setMessage(error);
//		messageBox.open();
//	}	
	
	
	
	@Override
	public void on_WoD_MapBoard_Change(WoD_MapBoard_Event event) {
		switch (event.getEvent_Type()) {
		case WoD_MapBoard_Event.Event_Types.MOVE:
			
			try {
				WoD_RT_Client_Movement clientMovement = (WoD_RT_Client_Movement) event.getData();
				
				byte[] message = woDNetProtocolManager.get_RT_Movement(clientMovement);
				woDClientRT.sendMessage(
						woDApplicationData.getWoDGame().getServerHost(), 
						woDApplicationData.getWoDGame().getServer_RT_Port(), 
						message);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			break;
			
		case WoD_MapBoard_Event.Event_Types.CLOSE:
			
			System.out.println("Closed");
			woDClientRT.getWoDUDPChannel().stop_Thread();
			
			
			
			
			break;

		default:
			break;
		}
		
	}
	
	
}
